#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <pthread.h>
#include "include.h"

//--------------------------------------------------------------------------

void * fsearch( void * tmp){
	struct data * array = ((struct thr1 *)tmp)->one;
	size_t size = ((struct thr1 *)tmp)->two;
	size_t id = ((struct thr1 *)tmp)->three;

	off_t k = 0, i;

	((struct thr1 *)tmp)->three = 1;	
	for( i = 0; i < size && array; i++){		
		if( array->n == id) break;
		k += array->sz;
		array = array->next;
		}
	if( i == size || !(array)) ((struct thr1 *)tmp)->three = 0;

	((struct thr1 *)tmp)->two = k;
	((struct thr1 *)tmp)->one = array;
};

//------------------------------------------------------------------------------

void clean( struct data* dis){
	struct data* one = dis->next;
	if( !(dis->last)){
		if(one) one->last = NULL;
		free(dis);
			}
	else{
		if(one) one->last = dis->last;
		(dis->last)->next = one;
		free(dis);
		}
};
		
//---------------------------------------------------------------------

int id_free(struct data* dis, struct block tmp, size_t i){
	struct data* one;
	struct data* two;
	int k = 0;
	int p = 0;
	if( dis->last){
		if( (dis->last)->sz || (dis->last)->n ){
			one = dis->last;
			}
		else{
			one =(dis->last)->last;
			p += 1;
			if(!one) {
				k += 1;
				p -= 1;
				}
			}
		}
	else{
		one = NULL;
		k += 1;
		}

	if( dis->next){
		if( (dis->next)->sz || (dis->next)->n ){
			two = dis->next;
			}
		else{
			two =(dis->next)->next;
			p += 2;
			if(!two) {
				k += 2;
				p -= 2;
				}
			}
		}
	else{
		two = NULL;
		k += 2;
		}
	
	if( k == 0){
		if( one->n && two->n){
			dis->n = 0;
			return 1;
			}		
		if( one->n){
			two->sz += dis->sz;
			clean(dis);
			tmp.sz[i]--;
			return 1;
			}
		if( two->n){
			one->sz += dis->sz;
			clean(dis);
			tmp.sz[i]--;
			return 1;
			}
		dis->n = 0;
		dis->sz += one->sz + two->sz;
		clean(one);
		clean(two);

		if( p >= 1) tmp.sz[i-1] -= 1;
		else  tmp.sz[i]--;
		if( p >= 2) tmp.sz[i+1] -= 1;
		else  tmp.sz[i]--;

		return 1;
	}
	
	if(k == 1){
		if( two->n){
			dis->n = 0;
			return 1;
			}
		dis->n = 0;
		dis->sz += two->sz;
		clean(two);

		if( p >= 2) tmp.sz[i+1] -= 1;
		else  tmp.sz[i] -= 1;
		return 1;
		}

	if(k == 2){
		if( one->n){
			dis->n = 0;
			return 1;
			}
		dis->n = 0;
		dis->sz += one->sz;
		clean(one);
		
		if( p >= 1) tmp.sz[i-1] -= 1;
		else  tmp.sz[i] -= 1;
		return 1;
	}

	if( k == 3){
		dis->n = 0;
		return 1;
		}
};

//-------------------------------------------------------------------

void * fsearch_fr( void * tmp){
	struct data * array = ((struct thr1 *)tmp)->one;
	size_t size = ((struct thr1 *)tmp)->two;
	size_t sz = ((struct thr1 *)tmp)->three;

	off_t i;

	((struct thr1 *)tmp)->three = 1;	
	for( i = 0; i < size && array; i++){		
		if( array->sz >= sz && !(array->n)) break;
		array = array->next;
		}
	if( i == size || !(array)) ((struct thr1 *)tmp)->three = 0;

	((struct thr1 *)tmp)->one = array;
};

//-------------------------------------------------------------------
	
size_t fadd(struct data* tmp, size_t sz, size_t id){ 
	if( tmp->sz == sz){
		tmp->n = id;
		tmp->rl = 0;
		return 0;
		}	

	struct data* one = (struct data*)malloc(sizeof(struct data));
	one->n = id;	
	one->sz = sz;
	one->rl = 0;
	one->last = tmp->last;
	(tmp->last)->next = one;
	one->next = tmp;
	tmp->last = one;
	tmp->sz -= sz;
	return 1;
};	
 
//------------------------------------------------------------------------------

size_t prepare1( struct block tmp){
	size_t i = tmp.n, k;	
	if(tmp.sz[i-1] <= SIZE) return i;

	struct data* one = (struct data*)malloc(sizeof(struct data));
	one->n = 0;
	one->sz = 0;
	one->rl = 0;
	
	struct data* two = tmp.st[i-1];
	for( k = 0; k < SIZE; k++){ 
		two = two->next;
		}
		
	(two->next)->last = one;
	one->next = two->next;
	one->last = two;
	two->next = one;
	
	tmp.st[i] = one;
	tmp.sz[i] = tmp.sz[i-1] - SIZE+1;
	tmp.sz[i] = SIZE;
	
	return i+1;
};
			
